home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 430_01 / m68kdis / fgen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-29  |  8.2 KB  |  389 lines

  1. /*
  2.  *                 Author:  Christopher G. Phillips
  3.  *              Copyright (C) 1994 All Rights Reserved
  4.  *
  5.  *                              NOTICE
  6.  *
  7.  * Permission to use, copy, modify, and distribute this software and
  8.  * its documentation for any purpose and without fee is hereby granted
  9.  * provided that the above copyright notice appear in all copies and
  10.  * that both the copyright notice and this permission notice appear in
  11.  * supporting documentation.
  12.  *
  13.  * The author makes no representations about the suitability of this
  14.  * software for any purpose.  This software is provided ``as is''
  15.  * without express or implied warranty.
  16.  */
  17.  
  18. /*
  19.  * MC68881/MC68882 FPU support.
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include "dis.h"
  26. #include "addr.h"
  27.  
  28. static char    *fccs[] = {
  29.     "F", "EQ", "OGT", "OGE", "OLT", "OLE", "OGL", "OR",
  30.     "UN", "UEQ", "UGT", "UGE", "ULT", "ULE", "NE", "T",
  31.     "SF", "SEQ", "GT", "GE", "LT", "LE", "GL", "GLE",
  32.     "NGLE", "NGL", "NLE", "NLT", "NGE", "NGT", "SNE", "ST"
  33. };
  34. #define NFCCS    (sizeof fccs / sizeof fccs[0])
  35.  
  36. /*
  37.  * Here come most of the math functions.
  38.  * fmath accounts for those after FSUB.
  39.  */
  40. static char    *names[] = {
  41.     "FMOVE", "FINT", "FSINH", "FINTRZ",
  42.     "FSQRT", NULL, "FLOGNP1", NULL,
  43.     "FETOXM1", "FTANH", "FATAN", NULL,
  44.     "FASIN", "FATANH", "FSIN", "FTAN",
  45.     "FETOX", "FTWOTOX", "FTENTOX", NULL,
  46.     "FLOGN", "FLOG10", "FLOG2", NULL,
  47.     "FABS", "FCOSH", "FNEG", NULL,
  48.     "FACOS", "FCOS", "FGETEXP", "FGETMAN",
  49.     "FDIV", "FMOD", "FADD", "FMUL",
  50.     "FSGLDIV", "FREM", "FSCALE", "FSGLMUL",
  51.     "FSUB"
  52. };
  53. #define NNAMES    (sizeof names / sizeof names[0])
  54.  
  55. char *
  56. fcc(unsigned condition)
  57. {
  58.     return (condition < NFCCS) ? fccs[condition] : NULL;
  59. }
  60.  
  61. int
  62. ftype2lis(int type)
  63. {
  64.     switch (type) {
  65.     case SINGLE:    return L_ISSINGLE;
  66.     case DOUBLE:    return L_ISDOUBLE;
  67.     case EXTENDED:    return L_ISEXTENDED;
  68.     case PACKED:    return L_ISPACKED;
  69.     default:    return -1;
  70.     }
  71. }
  72.  
  73. size_t
  74. fsizeof(int type)
  75. {
  76.     switch (type) {
  77.     case SINGLE:    return 2 * WORDSIZE;
  78.     case DOUBLE:    return 4 * WORDSIZE;
  79.     case EXTENDED:    return 6 * WORDSIZE;
  80.     case PACKED:    return 6 * WORDSIZE;
  81.     default:    return 0;
  82.     }
  83. }
  84.  
  85. static int
  86. srcreg2size(int srcreg)
  87. {
  88.     switch (srcreg) {
  89.     case 0: return LONGWORD;
  90.     case 1: return SINGLE;
  91.     case 2: return EXTENDED;
  92.     case 3: return PACKED;
  93.     case 4: return WORD;
  94.     case 5: return DOUBLE;
  95.     case 6: return BYTE;
  96.     default: return -1;
  97.     }
  98. }
  99.  
  100. static void
  101. fmovefromfp(m68kword inst, unsigned long value)
  102. {
  103.     int    size = (value >> 10) & 7;
  104.     int    srcreg = (value >> 7) & 7;
  105.     int    k = value & 0x7f;
  106.     int    reg = inst & 7;
  107.     int    mode = (inst >> 3) & 7;
  108.     
  109.     /*
  110.      * destreg and srcreg are switched so the
  111.      * call to srcreg2size is correct
  112.      * (size is playing the role of destreg)
  113.      */
  114.     if ((size = srcreg2size(size)) == -1) {
  115.         size = PACKED;
  116.         if (k & 0x40)
  117.             k |= ~0x7f;    /* sign-extend */
  118.         sprintf(buf3, "{#%d}", k);
  119.     } else if (size == PACKED) {
  120.         if (k & 0xf)
  121.             return;
  122.         sprintf(buf3, "{D%d}", (int)(k >> 4));
  123.     } else if (k)
  124.         return;    /* not sure here: manual says k ``should'' be 0 */
  125.  
  126.     sprintf(buf1, "FP%d", srcreg);
  127.  
  128. #define ISSINGLE(s)    ((s) == SINGLE)
  129.     if (ISDATA(mode) && !ISINTEGRAL(size) && !ISSINGLE(size)
  130.       || !ISADEA(mode, reg))
  131.         return;
  132. #undef ISSINGLE
  133.     if (getea(buf2, reg, mode, size))
  134.         return;
  135.     if (size == PACKED)
  136.         strcat(buf2, buf3);
  137.  
  138.     instprint(ops2f(2) | size2f(size), "FMOVE", buf1, buf2);
  139.  
  140.     valid = 1;
  141. }
  142.  
  143. static void
  144. fmovelist(m68kword inst, unsigned long value)
  145. {
  146.     int    to_ea = value & 0x2000;
  147.     int    reg = inst & 7;
  148.     int    mode = (inst >> 3) & 7;
  149.     char    *cp1, *cp2;
  150.     int    nregs;
  151.  
  152.     if (value & 0x3ff)
  153.         return;
  154.     if (to_ea && !ISADEA(mode, reg) && !ISDIRECT(mode))
  155.         return;
  156.  
  157.     cp1 = buf1;
  158.     *cp1 = '\0';
  159.     nregs = 0;
  160.     if (value & 0x1000) {
  161.         cp1 += sprintf(cp1, "FPCR");
  162.         nregs++;
  163.     }
  164.     if (value & 0x0800) {
  165.         if (cp1 != buf1)
  166.             *cp1++ = '/';
  167.         cp1 += sprintf(cp1, "FPSR");
  168.         nregs++;
  169.     }
  170.     if (value & 0x0400) {
  171.         if (cp1 != buf1)
  172.             *cp1++ = '/';
  173.         cp1 += sprintf(cp1, "FPIAR");
  174.         nregs++;
  175.     }
  176.     if (cp1 == buf1)
  177.         strcpy(cp1, "0");
  178.     
  179.     if (ISDATA(mode) && nregs != 1
  180.       || ISDIRECT(mode) && nregs != 1 && (value & 0x0400) == 0)
  181.         return;
  182.  
  183.     if (getea(buf2, reg, mode, LONGWORD))
  184.         return;
  185.  
  186.     if (to_ea) {
  187.         cp1 = buf1;
  188.         cp2 = buf2;
  189.     } else {
  190.         cp1 = buf2;
  191.         cp2 = buf1;
  192.     }
  193.  
  194.     instprint(ops2f(2) | size2f(LONGWORD), nregs == 1 ? "FMOVE" : "FMOVEM",
  195.       cp1, cp2);
  196.  
  197.     valid = 1;
  198. }
  199.  
  200. static void
  201. fmovem(m68kword inst, unsigned long value)
  202. {
  203.     int        to_ea = value & 0x2000;
  204.     int        eareg = inst & 7;
  205.     int        eamode = (inst >> 3) & 7;
  206.     int        mode = (value >> 11) & 3;
  207.     unsigned long    reglist = value & 0xff;
  208.     char        *cp1, *cp2;
  209.  
  210.     if (value & 0x0700)
  211.         return;
  212.  
  213.     if (to_ea) {
  214.         if (!ISACEAplusPRE(eamode, eareg))
  215.             return;
  216.     } else if (!ISCEAplusPOST(eamode, eareg))
  217.         return;
  218.  
  219.     /*
  220.      * Note that (mode & 2) implies postincrement or control
  221.      * addressing mode, otherwise predecrement addressing mode
  222.      *
  223.      * Not sure what this means though...
  224.      */
  225.     if (mode & 1) {
  226.         /*
  227.          * Dynamic list
  228.          */
  229.         if (value & 0x8f)
  230.             return;
  231.         sprintf(buf1, "D%d", (int)((value >> 4) & 7));
  232.     } else {
  233.         /*
  234.          * Static list
  235.          */
  236.         if (mode & 2)
  237.             revbits(®list, 8);
  238.         regbyte(buf1, reglist, "FP", 0);
  239.     }
  240.  
  241.     if (getea(buf2, eareg, eamode, EXTENDED))
  242.         return;
  243.  
  244.     if (to_ea) {
  245.         cp1 = buf1;
  246.         cp2 = buf2;
  247.     } else {
  248.         cp1 = buf2;
  249.         cp2 = buf1;
  250.     }
  251.  
  252.     instprint(ops2f(2) | size2f(EXTENDED), "FMOVEM", cp1, cp2);
  253.  
  254.     valid = 1;
  255. }
  256.  
  257. static void
  258. fmath(m68kword inst, unsigned long value)
  259. {
  260.     int    reg = inst & 7;
  261.     int    mode = (inst >> 3) & 7;
  262.     int    srcreg = (value >> 10) & 7;
  263.     int    destreg = (value >> 7) & 7;
  264.     int    cosreg = value & 7;
  265.     int    use_ea = value & 0x4000;
  266.     int    size;
  267.     size_t    name_index = value & 0x7f;
  268.     int    nops;
  269.     char    *name = NULL;
  270.  
  271.     size = EXTENDED;
  272.     nops = 2;
  273.     if (name_index == 0x3a) {
  274.         name = "FTST";
  275.         nops = 1;
  276.         sprintf(buf2, "FP%d", destreg);
  277.     } else if (name_index >= 0x30 && name_index <= 0x37) {
  278.         name = "FSINCOS";
  279.         sprintf(buf2, "FP%d:FP%d", cosreg, destreg /* sine reg */);
  280.     } else {
  281.         sprintf(buf2, "FP%d", destreg);
  282.         if (name_index < NNAMES)
  283.             name = names[name_index];
  284.         else if (name_index == 0x38)
  285.             name = "FCMP";
  286.     }
  287.     if (!name)
  288.         return;
  289.  
  290. #define ISSINGLE(s)    ((s) == SINGLE)
  291.     if (use_ea) {
  292.         if ((size = srcreg2size(srcreg)) == -1)
  293.             return;
  294.         if (ISDIRECT(mode) || ISDATA(mode) && !ISINTEGRAL(size)
  295.           && !ISSINGLE(size))
  296. #undef ISSINGLE
  297.             return;
  298.         if (getea(nops == 1 ? buf2 : buf1, reg, mode, size))
  299.             return;
  300.     } else {
  301.         if (mode || reg)
  302.             return;
  303.         if (srcreg == destreg && name_index < 0x20)
  304.             nops = 1;
  305.         else
  306.             sprintf(buf1, "FP%d", srcreg);
  307.     }
  308.  
  309.     if (nops == 1)
  310.         instprint(ops2f(1) | size2f(size), name, buf2);
  311.     else
  312.         instprint(ops2f(2) | size2f(size), name, buf1, buf2);
  313.  
  314.     valid = 1;
  315. }
  316.  
  317. static void
  318. fmovecr(unsigned long value)
  319. {
  320.     int    reg = (value >> 7) & 7;
  321.     int    offset = value & 0x7f;
  322.  
  323.     sprintf(buf2, "FP%d", reg);
  324.  
  325.     immsprintf(buf1, offset);
  326.     switch (offset) {
  327.     case 0x00:    strcat(buf1, "!PI");    break;
  328.     case 0x0b:    strcat(buf1, "!Log10(2)");    break;
  329.     case 0x0c:    strcat(buf1, "!e");    break;
  330.     case 0x0d:    strcat(buf1, "!Log2(e)");    break;
  331.     case 0x0e:    strcat(buf1, "!Log10(e)");    break;
  332.     case 0x0f:    strcat(buf1, "!0.0");    break;
  333.     case 0x30:    strcat(buf1, "!1n(2)");    break;
  334.     case 0x31:    strcat(buf1, "!1n(10)");    break;
  335.     case 0x32:    strcat(buf1, "!10^0");    break;
  336.     case 0x33:    strcat(buf1, "!10^1");    break;
  337.     case 0x34:    strcat(buf1, "!10^2");    break;
  338.     case 0x35:    strcat(buf1, "!10^4");    break;
  339.     case 0x36:    strcat(buf1, "!10^8");    break;
  340.     case 0x37:    strcat(buf1, "!10^16");    break;
  341.     case 0x38:    strcat(buf1, "!10^32");    break;
  342.     case 0x39:    strcat(buf1, "!10^64");    break;
  343.     case 0x3a:    strcat(buf1, "!10^128");    break;
  344.     case 0x3b:    strcat(buf1, "!10^256");    break;
  345.     case 0x3c:    strcat(buf1, "!10^512");    break;
  346.     case 0x3d:    strcat(buf1, "!10^1024");    break;
  347.     case 0x3e:    strcat(buf1, "!10^2048");    break;
  348.     case 0x3f:    strcat(buf1, "!10^4096");    break;
  349.     }
  350.  
  351.     instprint(ops2f(2), "FMOVECR", buf1, buf2);
  352.  
  353.     valid = 1;
  354. }
  355.  
  356. void
  357. fgen(m68kword inst)
  358. {
  359.     unsigned long    value;
  360.     int        failure;
  361.  
  362.     value = getval(WORD, &failure) & 0xffff;
  363.     if (failure)
  364.         return;
  365.  
  366.     if ((inst & 0x7f) == 0 && (value & 0xfc00) == 0x5c00)
  367.         fmovecr(value);
  368.     else
  369.         switch ((value >> 13) & 7) {
  370.         case 0: /* FALLTHROUGH */
  371.         case 2:
  372.             fmath(inst, value);
  373.             break;
  374.         case 3:
  375.             fmovefromfp(inst, value);
  376.             break;
  377.         case 4: /* FALLTHROUGH */
  378.         case 5:
  379.             fmovelist(inst, value);
  380.             break;
  381.         case 6: /* FALLTHROUGH */
  382.         case 7:
  383.             fmovem(inst, value);
  384.             break;
  385.         default:
  386.             return;
  387.         }
  388. }
  389.